package com.jmxcfc.blfsc.jiwei.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.TypeReference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jmxcfc.blfsc.common.exception.NotifyException;
import com.jmxcfc.blfsc.common.sms.enums.MsgTypeEnum;
import com.jmxcfc.blfsc.common.sms.enums.SendStatusEnum;
import com.jmxcfc.blfsc.common.sms.notify.NotifyDataItem;
import com.jmxcfc.blfsc.common.sms.notify.ResultNotifyRequest;
import com.jmxcfc.blfsc.jiwei.common.Constants;
import com.jmxcfc.blfsc.jiwei.entity.SmsNotifyRecord;
import com.jmxcfc.blfsc.jiwei.feign.ISmsClientService;
import com.jmxcfc.blfsc.jiwei.service.ISmsNotifyRecordService;
import com.jmxcfc.blfsc.jiwei.service.ISmsNotifyRequestService;
import com.jmxcfc.fs.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 功能描述
 *
 * @author: pay
 * @date: 2024年06月23日 23:25
 */
@Service
@Slf4j
@Transactional(rollbackFor = RuntimeException.class)
public class SmsNotifyRequestServiceImpl implements ISmsNotifyRequestService {

    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    private ISmsClientService smsClientService;
    private ISmsNotifyRecordService smsNotifyRecordService;


    @Autowired
    public void setSmsNotifyRecordService(ISmsNotifyRecordService smsNotifyRecordService) {
        this.smsNotifyRecordService = smsNotifyRecordService;
    }

    @Autowired
    public void setThreadPoolTaskExecutor(ThreadPoolTaskExecutor threadPoolTaskExecutor) {
        this.threadPoolTaskExecutor = threadPoolTaskExecutor;
    }

    @Autowired
    public void setSmsClientService(ISmsClientService smsClientService) {
        this.smsClientService = smsClientService;
    }
    /**
     * 处理异步通知数据,处理成功则 返回 ok(若返回其他值任意值，则为接收推送的状态报告失败。我方对于接收失败的会进行三次的重新推送)
     * 处理过程:
     * 1、遍历每条数据:
     * (1)数据落库
     * (2)短信状态判断:errorCode:0表示成功、其他错误码均表示下发失败
     * 2、发送通知的消息队列,到时候blfs-sms消费者进行消费处理
     * @param notifyData
     * @return
     */
    @Override
    public String notifyHandler(JSONObject notifyData) {
        //由于每次推送的transactionId不一致,进行重复推送的校验
        String transactionId = notifyData.getString(Constants.TRANSACTION_ID);
        String handlerResult = "OK";
        try{
            List<JSONObject> reportsList = JSON.parseObject(JSON.toJSONString(notifyData.get(Constants.REPORTS)), new TypeReference<List<JSONObject>>() {
            });
            ResultNotifyRequest<JSONObject> notifyRequest = ResultNotifyRequest.of(MsgTypeEnum.SMS);
            if (smsNotifyRecordService.isNotExist(transactionId)) {
                //通知表留痕
                List<SmsNotifyRecord> smsNotifyRecordList = new ArrayList<>(reportsList.size());
                //通知blfs-sms请求参数
                List<NotifyDataItem> notifyDataItemList = new ArrayList<>(reportsList.size());

                reportsList.forEach(reportItemJSONObject -> {
                    //todo暂时不查询
                    /*if (StringUtils.isBlank(SmsNotifyRequest.getRequestNo())) {
                        SendDetailSub sendDetailSub = sendDetailSubService.getById(reportItemJSONObject.getString(Constants.UUID));
                        if (Objects.nonNull(sendDetailSub)) {
                            SmsNotifyRequest.setRequestNo(sendDetailSub.getRequestNo());
                            SmsNotifyRequest.setBatchId(sendDetailSub.getTransactionId());
                        }
                    }*/

                    SmsNotifyRecord smsNotifyRecord = new SmsNotifyRecord();
                    //字段赋值:userId、mobile、errorCode、errorDesc、time、uuid、subSeq
                    BeanUtil.copyProperties(reportItemJSONObject,smsNotifyRecord);
                    smsNotifyRecord.setTransactionId(transactionId);
                    smsNotifyRecordList.add(smsNotifyRecord);

                    //通知blfs-sms数据赋值
                    NotifyDataItem notifyDataItem = new NotifyDataItem();
                    notifyDataItem.setUuid(smsNotifyRecord.getUuid());
                    notifyDataItem.setMobile(smsNotifyRecord.getMobile());
                    notifyDataItem.setMsgTotal(StringUtils.isBlank(smsNotifyRecord.getSubSeq())?"0":smsNotifyRecord.getSubSeq());

                    // //判断发送状态是否成功还是失败:errorCode:0表示成功、其他错误码均表示下发失败
                    notifyDataItem.setSmsSendStatus(StringUtils.equals("0", reportItemJSONObject.getString(Constants.ERROR_CODE)) ? SendStatusEnum.SUCCESS : SendStatusEnum.FAILURE);
                    notifyDataItem.setSmsSendStatusDesc(notifyDataItem.getSmsSendStatus().desc());
                    notifyDataItem.setErrorCode(smsNotifyRecord.getErrorCode());
                    notifyDataItem.setErrorDesc(smsNotifyRecord.getErrorDesc());
                    notifyDataItemList.add(notifyDataItem);
                });
                smsNotifyRecordService.saveBatch(smsNotifyRecordList);
                log.info("集微短信状态推送,transactionId(对方推送的事务Id):{},保存通知数据到数据库JIWEI_SMS_NOTIFY_RECORD(集微通知表),数据条数:{}", transactionId,smsNotifyRecordList.size());

                List<NotifyDataItem> noDuplicateNotifyData = getNoDuplicateElements(notifyDataItemList);
                log.info("集微短信状态推送,transactionId(对方推送的事务Id):{},通知数据:根据uuid去除集合重复的值,取subSeq(短信拆分标识)最大的值后数据:{}", transactionId, JSON.toJSONString(noDuplicateNotifyData));
                //剔除uuid、电话号码重复的数据且保留subSeq(短信拆分最大的数据)
                notifyRequest.setNotifyDataList(noDuplicateNotifyData);
                notifyRequest.setEndTime(LocalDateTime.now());
                //异步调用blfs-sms
                threadPoolTaskExecutor.execute(() -> sendNotifyResult(transactionId,notifyRequest));
            }else {
                log.error("集微短信状态推送,数据库已经存在transactionId:{},重复推送数据", transactionId);
                handlerResult =  "ERROR";
            }
        }catch (Exception e){
            log.error("集微短信状态异步通知处理异常:{}",e.getMessage(),e);
            throw new NotifyException(e);
        }
        return handlerResult;
    }


    /**
     * 根据uuid去除集合重复的值,取subSeq(短信拆分标识)=>msgTotal最大的值
     * @param notifyDataItemList
     * @return
     */
    private List<NotifyDataItem> getNoDuplicateElements(List<NotifyDataItem> notifyDataItemList){
        return notifyDataItemList.stream()
                .collect(Collectors.groupingBy(NotifyDataItem::getUuid))
                .values().stream().map(groupedList -> groupedList.stream()
                        .collect(Collectors.collectingAndThen(
                                Collectors.maxBy(Comparator.comparing(NotifyDataItem::getMsgTotal)),
                                Optional::get)))
                .collect(Collectors.toList());
    }

    /**
     * 发送异步通知,调用blfs-sms
     * @param transactionId
     * @param smsNotifyRequest
     * @return
     */
    private void sendNotifyResult(String transactionId, ResultNotifyRequest<JSONObject> smsNotifyRequest) {
        try {
            log.info("transactionId(对方推送的事务Id):{},短信状态异步通知调用blfs-sms,调用参数:{}",transactionId,JSON.toJSONString(smsNotifyRequest));
            Result<Object> result = smsClientService.receiveNotify(JSON.parseObject(JSON.toJSONString(smsNotifyRequest)));
            log.info("transactionId(对方推送的事务Id):{},短信状态异步通知调用blfs-sms,响应结果:{}",transactionId,result);
        } catch (Exception e) {
            log.error("transactionId(对方推送的事务Id):{},集微短信状态异步通知处理异常,调用blfs-sms 异常,异常信息:{}", transactionId, e.getMessage(), e);
            //throw new NotifyException(e);
        }
    }
}